#! /usr/bin/env python
# -*- coding: utf-8 -*-
'''
Created on 14 mai 2011

@author: nathanael
'''

import re, threading

from pybible.core.result import ResultsFactory



class RequestI(object):
    "Request is base object for found something."
    def math(self, text):
        "The pattern math the given text."
    def finditer(self, text):
        "Iter eatch results into given text."



class RegexRequest(RequestI):
    "Pattern using Regex tool."
    def __init__(self, pattern):
        "Init the pattern by string."
        self.regex = pattern
        self.cregex = re.compile(pattern)

    def get_regex(self):
        "Return valid regular expression"
        return self.regex

    #
    # Implement pattern interface.
    #
    def math(self, text):
        return self.cregex.search(text) != None

    def finditer(self, text):
        for match in self.cregex.finditer(text):
            yield (match.start(0), match.end(0), match.group(0))


def RequestFactory():
    """Build new request factory.
    """
    def request_factory_(*argv, **kw):
        return RegexRequest(*argv, **kw)
    return request_factory_



class FindKernel(object):
    "Kernel used to find all results"
    def __init__(self, pattern=None,
                 results_factory=ResultsFactory()):
        ""
        self._pattern = pattern
        self._factory = results_factory
        self._results = results_factory.new_results()

    def set_request(self, req):
        self._pattern = req

    def get_results_factory(self):
        return self._factory

    def get_results(self):
        "Return results object. There are only one results object for a kernel."
        return self._results

    def clear(self):
        "Clear all results."
        self._results.values = []

    def eval(self, element, ref):
        "Eval the given element and store the results"
        xpath = element.get_xpath()
        text = element.text
        if (text != None and self._pattern.math(text)):
            self._results.append(self._factory.new_result\
                                 (element, xpath, self._pattern.regex, ref))

    def _regex_find(self, element):
        find = "//verse[re:match(text(), '%s')]" % (self._pattern.get_regex())

        def factory(item):
            return self._factory.new_result\
                (item, item.get_xpath(), self._pattern.regex, element)

        results = element.eval_xpath(find, factory=factory,
                                     namespaces={"re": "http://exslt.org/regular-expressions"})
        self._results.extend(results)

    def _iter_find(self, element, wait=False):
        def find():
            for item in element.iter():
                self.eval(item, element)

        if not wait:
            threading.Thread(None, find, None, (), {}).start()
        else:
            find()
        return self._results


    def find(self, element, wait=False):
        "Find all into given element."

        if hasattr(self._pattern, 'get_regex'):
            self._regex_find(element)
        else:
            self._iter_find(element, wait)

        return self._results

